/*
 * Copyright (c) 2003-2006 jMonkeyEngine, 2007 Aleksey Nikiforov
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * * Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * * Neither the name of 'jMonkeyEngine' nor the names of its contributors 
 *   may be used to endorse or promote products derived from this software 
 *   without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package org.lex.game;

import java.util.logging.Level;
import java.util.logging.Logger;

import javax.swing.ImageIcon;

import org.lex.input.StrategicHandler;
import org.lex.input.effects.HeightMap;
import org.lex.input.mouse.MouseManager;
import org.lex.input.mouse.component.CombinedMouse;

import com.jme.app.SimpleGame;
import com.jme.image.Texture;
import com.jme.light.DirectionalLight;
import com.jme.math.Vector3f;
import com.jme.renderer.ColorRGBA;
import com.jme.scene.Node;
import com.jme.scene.state.CullState;
import com.jme.scene.state.FogState;
import com.jme.scene.state.TextureState;
import com.jme.util.TextureManager;
import com.jmex.terrain.TerrainPage;
import com.jmex.terrain.util.FaultFractalHeightMap;
import com.jmex.terrain.util.ProceduralTextureGenerator;

public class SimpleSetup extends SimpleGame {

	private TerrainPage terrain;
	private StrategicHandler strategicHandler;
	
	
	public static void main(String[] args) {
		Logger.getLogger("").setLevel(Level.WARNING);
		SimpleSetup game = new SimpleSetup();
		game.setConfigShowMode(ConfigShowMode.AlwaysShow);
		game.start();
	}
	
	@Override
	protected void simpleInitGame() {
		setupTerrain();
		setupHandler();
	}
	
	public void setupHandler() {
		HeightMap heightMap = new HeightMap() {
			public float getHeightAt(Vector3f location) {
				float height = terrain.getHeight(location);
				if (Float.isNaN(height)) height = 0;
				return height;
			}
		};
		MouseManager mouseManager = new MouseManager(CombinedMouse.get());
		strategicHandler = new StrategicHandler(
				cam, mouseManager, heightMap);
		input = strategicHandler;
		
		mouseManager.registerWithInputHandler(strategicHandler);
		mouseManager.setMousePosition(
				display.getWidth()/2, display.getHeight()/2);
		statNode.attachChild(mouseManager.getMouse().getMouseSpatial());
	}
	
	public void setupTerrain() {
		Node terrainNode = new Node();
		rootNode.attachChild(terrainNode);
		
		// this piece is pretty much copied from the jme terrain test
		
		FaultFractalHeightMap heightMap = new FaultFractalHeightMap(
				257, 32, 0, 255, 0.75f);
	    Vector3f terrainScale = new Vector3f(10,1,10);
	    heightMap.setHeightScale( 0.001f);
	    terrain = new TerrainPage("Terrain", 33,
	    		heightMap.getSize(), terrainScale,
	    		heightMap.getHeightMap());

	    terrain.setDetailTexture(1, 16);
	    terrainNode.attachChild(terrain);
	    
	    ProceduralTextureGenerator pt = new ProceduralTextureGenerator(heightMap);
	    pt.addTexture(new ImageIcon(SimpleSetup.class.getClassLoader().getResource(
        	"jmetest/data/texture/grassb.png")), -128, 0, 128);
	    pt.addTexture(new ImageIcon(SimpleSetup.class.getClassLoader().getResource(
        	"jmetest/data/texture/dirt.jpg")), 0, 128, 255);
	    pt.addTexture(new ImageIcon(SimpleSetup.class.getClassLoader().getResource(
        	"jmetest/data/texture/highest.jpg")), 128, 255, 384);

	    pt.createTexture(512);

	    TextureState ts = display.getRenderer().createTextureState();
	    ts.setEnabled(true);
	    Texture t1 = TextureManager.loadTexture(
	        pt.getImageIcon().getImage(),
	        Texture.MinificationFilter.Trilinear, 
	        Texture.MagnificationFilter.Bilinear,
	        true);
	    ts.setTexture(t1, 0);

	    Texture t2 = TextureManager.loadTexture(
    		Demo.class.getClassLoader().getResource("jmetest/data/texture/Detail.jpg"),
			Texture.MinificationFilter.Trilinear, 
	        Texture.MagnificationFilter.Bilinear);
	    
	    ts.setTexture(t2, 1);
	    t2.setWrap(Texture.WrapMode.Repeat);

	    t1.setApply(Texture.ApplyMode.Combine);
	    t1.setCombineFuncRGB(Texture.CombinerFunctionRGB.Modulate);
	    t1.setCombineSrc0RGB(Texture.CombinerSource.CurrentTexture);
	    t1.setCombineOp0RGB(Texture.CombinerOperandRGB.SourceColor);
	    t1.setCombineSrc1RGB(Texture.CombinerSource.PrimaryColor);
	    t1.setCombineOp1RGB(Texture.CombinerOperandRGB.SourceColor);

	    t2.setApply(Texture.ApplyMode.Combine);
        t2.setCombineFuncRGB(Texture.CombinerFunctionRGB.AddSigned);
        t2.setCombineSrc0RGB(Texture.CombinerSource.CurrentTexture);
        t2.setCombineOp0RGB(Texture.CombinerOperandRGB.SourceColor);
        t2.setCombineSrc1RGB(Texture.CombinerSource.Previous);
        t2.setCombineOp1RGB(Texture.CombinerOperandRGB.SourceColor);
        
	    terrainNode.setRenderState(ts);

	    FogState fs = display.getRenderer().createFogState();
	    fs.setDensity(0.0015f);
	    fs.setEnabled(true);
	    fs.setColor(new ColorRGBA(0.5f, 0.55f, 0.5f, 0.5f));
	    fs.setDensityFunction(FogState.DensityFunction.Exponential);
	    fs.setQuality(FogState.Quality.PerVertex);
	    terrainNode.setRenderState(fs);
	    
	    terrainNode.lock();
	    terrainNode.lockBranch();
	    
	    CullState cs = display.getRenderer().createCullState();
	    cs.setCullFace(CullState.Face.Back);
	    cs.setEnabled(true);
	    terrainNode.setRenderState(cs);
	    
	    lightState.detachAll();
	    
	    DirectionalLight dl = new DirectionalLight();
	    dl.setDiffuse(new ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f));
	    dl.setDirection(new Vector3f(1, -0.5f, 1));
	    dl.setEnabled(true);
	    lightState.attach(dl);
	    
	    DirectionalLight dr = new DirectionalLight();
	    dr.setEnabled(true);
	    dr.setDiffuse(new ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f));
	    dr.setAmbient(new ColorRGBA(0.5f, 0.5f, 0.5f, 1.0f));
	    dr.setDirection(new Vector3f(0.5f, -0.5f, 0).normalizeLocal());
	    lightState.attach(dr);
	}
	
	@Override
	protected void simpleUpdate() {
		/*
		 * Remember to update your cursor every frame. You will want to
		 * do this, because after you do mouse picking you can choose
		 * differet cursors based on the result of the mouse pick.
		 * 
		 * Example: you can set a different cursor when the mouse is
		 * hovering over an enemy vs the default cursor.
		*/
		strategicHandler.useCursor("default");
	}

}
